package com.vicent.controller;


import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.AlipaySignature;
import com.vicent.config.AliPayClientConfig;
import com.vicent.entity.OrderInfo;
import com.vicent.service.AliPayService;
import com.vicent.service.OrderInfoService;
import com.vicent.vo.R;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Map;

/**
 * <p> ali支付 </p>
 *
 * @author vincent
 * @since 2023-09-01
 */
@Slf4j
@RestController
@RequestMapping("/api/ali-pay")
public class AliPayController {

    @Autowired
    private AliPayService aliPayService;
    @Autowired
    private AliPayClientConfig aliPayClientConfig;
    @Autowired
    private OrderInfoService orderInfoService;

    @CrossOrigin
    @ApiOperation("商品列表")
    @PostMapping("/trade/page/pay/{productId}")
    public R tradePagePay(@PathVariable Long productId){
        log.info("统一收单下单并支付页面接口的调用");
        //为了将主动权交给用户，支付宝接口用户下单的请求后，会生成一个from表单返回给用户并且自动提交，展示用户登录支付宝的页面开始支付
        //交互流程：
        // 1、用户点击下单，传递进行订单参数，完成下单
        // 2、将商户系统的订单参数以及商品参数组装成支付宝下单请求参数，发起支付
        // 3、支付宝返回一个from表单，通过商户系统返回给用户，用户浏览器自动提交表单，到达支付宝支付登录页面
        // 4、用户登录后完成支付，跳转到同步通知页面
        String formStr = aliPayService.treadeCreate(productId);
        return R.ok().data("formStr",formStr);
    }

    @ApiOperation("支付通知")
    @PostMapping("/trade/notify")
    public String tradeNotify(@RequestParam Map<String, String> params){
        log.info("支付通知,params:{}",params);
        String result = "failure";
        try {
            //异步通知验签(调用SDK验证签名)
            boolean signVerified = AlipaySignature.rsaCheckV1(params,aliPayClientConfig.getAlipayPublicKey(), AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);
            if(!signVerified){
                log.error("支付成功异步通知验签失败！");
                return result;
            }
            // 验签成功后
            log.info("支付成功异步通知验签成功！");

            //按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，
            //1 商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号
            String outTradeNo = params.get("out_trade_no");
            OrderInfo order = orderInfoService.getOrderByOrderNo(outTradeNo);
            if(order == null){
                log.error("订单不存在");
                return result;
            }
            //2 判断 total_amount 是否确实为该订单的实际金额（即商户订单创建时的金额）
            String totalAmount = params.get("total_amount");
            int totalAmountInt = new BigDecimal(totalAmount).multiply(new BigDecimal("100")).intValue();
            int totalFeeInt = order.getTotalFee().intValue();
            if(totalAmountInt != totalFeeInt){
                log.error("金额校验失败");
                return result;
            }

            //3 校验通知中的 seller_id（或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方
            String sellerId = params.get("seller_id");
            String sellerIdProperty = aliPayClientConfig.getSellerId();
            if(!sellerId.equals(sellerIdProperty)){
                log.error("商家pid校验失败");
                return result;
            }
            //4 验证 app_id 是否为该商户本身
            String appId = params.get("app_id");
            String appIdProperty = aliPayClientConfig.getAppId();
            if(!appId.equals(appIdProperty)){
                log.error("appid校验失败");
                return result;
            }
            //在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS时，支付宝才会认定为买家付款成功。
            String tradeStatus = params.get("trade_status");
            if(!"TRADE_SUCCESS".equals(tradeStatus)){
                log.error("支付未成功");
                return result;
            }
            //处理业务 修改订单状态 记录支付日志
            aliPayService.processOrder(params);
            //校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
            result = "success";
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return result;
    }

    @CrossOrigin
    @ApiOperation("取消订单")
    @PostMapping("/trade/close/{orderNo}")
    public void close(@PathVariable String orderNo){
        log.info("取消订单接口的调用");
        aliPayService.cancelOrder(orderNo);
    }

    @CrossOrigin
    @ApiOperation("查询订单")
    @PostMapping("/trade/query/{orderNo}")
    public R queryOrder(@PathVariable String orderNo){
        log.info("查询订单接口的调用");
        String result = aliPayService.queryOrder(orderNo);
        return R.ok().setMessage("查询成功").data("result", result);
    }

    /**
     * 申请退款
     * @param orderNo
     * @param reason
     * @return
     */
    @CrossOrigin
    @ApiOperation("申请退款")
    @PostMapping("/trade/refund/{orderNo}/{reason}")
    public R refunds(@PathVariable String orderNo, @PathVariable String reason){

        log.info("申请退款");
        aliPayService.refund(orderNo, reason);
        return R.ok();
    }

    /**
     * 查询退款
     * @param orderNo
     * @return
     * @throws Exception
     */
    @ApiOperation("查询退款：测试用")
    @GetMapping("/trade/fastpay/refund/{orderNo}")
    public R queryRefund(@PathVariable String orderNo) throws Exception {

        log.info("查询退款");

        String result = aliPayService.queryRefund(orderNo);
        return R.ok().setMessage("查询成功").data("result", result);
    }
}
